package com.boarsoft.boar.soagov.flow.action;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.common.Constants;
import com.boarsoft.boar.entity.ComInfo;
import com.boarsoft.boar.entity.FlowInfo;
import com.boarsoft.boar.entity.ObjFaces;
import com.boarsoft.boar.entity.SoaNexus;
import com.boarsoft.boar.entity.SvcInfo;
import com.boarsoft.boar.soagov.ObjFacesBiz;
import com.boarsoft.boar.soagov.flow.FlowInfoBiz;
import com.boarsoft.boar.soagov.nexus.NexusBiz;
import com.boarsoft.boar.soagov.svc.SvcBiz;
import com.boarsoft.common.Authorized;
import com.boarsoft.common.Util;
import com.boarsoft.common.dao.PagedResult;
import com.boarsoft.common.util.Base64;
import com.boarsoft.common.util.BeanUtil;
import com.boarsoft.common.util.FileUtil;
import com.boarsoft.common.util.JsonUtil;
import com.boarsoft.flow.store.SimpleFlowStore;

/**
 * 流程图服务
 *
 * @author Mac_J
 */
@RestController
@RequestMapping("/flow")
public class FlowInfoAction {
	private static final Logger log = LoggerFactory.getLogger(FlowInfoAction.class);

	@Autowired
	private NexusBiz nexusBiz;
	@Autowired
	private ObjFacesBiz objFacesBiz;
	@Autowired
	private FlowInfoBiz flowInfoBiz;
	@Autowired
	private SimpleFlowStore flowStore;
	@Autowired
	private SvcBiz svcBiz;

	@SuppressWarnings("unchecked")
	@RequestMapping("/save.do")
	@Authorized(code = "flow.save")
	public ReplyInfo<Object> save(FlowInfo fo, String id, String nexus, String faces, String json, String thumb) {
		// 更新或保存对象
		flowInfoBiz.save(fo);
		// 保存与组件的关系（先删除，再添加）
		List<SoaNexus> nLt = new ArrayList<SoaNexus>();
		log.info(nexus);
		// List<Map<String, Object>> mLt = new Gson().fromJson(nexus,
		// ArrayList.class);
		List<Map<String, Object>> mLt = JsonUtil.parseObject(nexus, ArrayList.class);
		SoaNexus z = null;
		for (Map<String, Object> m : mLt) {
			z = new SoaNexus();
			BeanUtil.fillObjectWithMap(z, m);
			log.info(JsonUtil.from(z));
			nLt.add(z);
		}
		// 保存与接口的关系
		String[] fa = faces.split(",");
		for (String faceId : fa) {
			ObjFaces n = new ObjFaces();
			n.setObjId(id);
			n.setObjType(ComInfo.TYPE_SUBFLOW);
			n.setFaceId(faceId);
			objFacesBiz.save(n);// 此方法会检查objId0和objId1的依赖是否存在
		}
		// 保存图表（此路径与导出路径不同）
		// DirInfo d = dirBiz.get(id);// flowId与dirId相同
		// StringBuilder sb = new StringBuilder();
		// sb.setLength(0);
		// sb.append(Config.PATH_PRIVATE).append(d.getPath());
		// sb.append("/").append(d.getCode()).append("/diagram.js");
		// sb.append(Config.PATH_PRIVATE).append("/").append(id).append("/diagram.js");
		// String pv = sb.toString();
		String pv = flowStore.getDiagramPath(id).concat("/diagram.js");
		log.info("Save flow diagram json to {}", pv);
		try {
			File fj = new File(pv);
			FileUtil.makePath(fj.getParent());
			FileUtil.write(fj, json);
		} catch (Exception e) {
			log.error("Error on save flow diagram json to {}", pv, e);
			return new ReplyInfo<Object>(Constants.ERROR_UNKNOWN, "Msg.flow.save");
		}
		// sb.setLength(0);
		// sb.append(Config.PATH_PRIVATE).append(d.getPath());
		// sb.append("/").append(d.getCode()).append("/diagram.png");
		// sb.append(Config.PATH_PRIVATE).append("/").append(id).append("/diagram.png");
		// String pb = sb.toString();
		String pb = flowStore.getDiagramPath(id).concat("/diagram.png");
		String[] pd = thumb.split(",");
		log.info("Save flow diagram thumb to {}", pd, pb);
		try {
			File fp = new File(pb);
			FileUtil.makePath(fp.getParent());
			Files.write(fp.toPath(), Base64.decode(pd[1]));
			return ReplyInfo.SUCCESS;
		} catch (Exception e) {
			log.error("Error on save flow diagram thumb to {}", pb, e);
			return new ReplyInfo<Object>(Constants.ERROR_UNKNOWN, "Msg.flow.save");
		}
	}

	@RequestMapping("/load.do")
	@Authorized(code = "flow.load")
	public ReplyInfo<Object> load(String id) {
		// DirInfo d = dirBiz.get(id);// flowId与dirId相同
		// if (d == null) {
		// writeTextReply(Constants.ERROR_NOTFOUND);
		// return;
		// }

		String pv = flowStore.getDiagramPath(id).concat("/diagram.js");
		File f = new File(pv);
		log.info("Load flow diagram json from {}", pv);
		try {
			// File f = new File(pv);
			if (f.exists()) {
				String json = FileUtil.read(f);
				return new ReplyInfo<Object>(true, json);
			} else {
				return ReplyInfo.SUCCESS;
			}
		} catch (Exception e) {
			log.error("Error on load flow diagram json from {}", pv, e);
			return new ReplyInfo<Object>(Constants.ERROR_UNKNOWN, "Msg.flow.load");
		}
	}

	@RequestMapping("/thumb.do")
	@Authorized(code = "flow.thumb")
	public ReplyInfo<Object> thumb(HttpServletResponse rsp, String id, String url) {
		// DirInfo d = dirBiz.get(id);// flowId与dirId相同
		// StringBuilder sb = new StringBuilder();
		// sb.append(Config.PATH_PRIVATE).append(d.getPath());
		// sb.append("/").append(d.getCode()).append("/diagram.png");
		// String pv = sb.toString();
		String pv = flowStore.getDiagramPath(id).concat("/diagram.png");
		log.info("Load flow diagram thumb from {}", pv);
		try {
			File f = new File(pv);
			if (f.exists()) {
				byte[] ba = Files.readAllBytes(f.toPath());
				if (Util.strIsEmpty(url)) {
					rsp.setContentType("image/png");
					ServletOutputStream os = rsp.getOutputStream();
					os.write(ba);
					rsp.flushBuffer();
				} else {
					return new ReplyInfo<Object>(true, "data:image/png;base64,".concat(Base64.encode(ba)));
				}
			}
			return new ReplyInfo<Object>(Constants.ERROR_NOTFOUND, "Msg.flow.diagram");
		} catch (Exception e) {
			try {
				rsp.getOutputStream().close();
			} catch (IOException e1) {
			}
			log.error("Error on load flow diagram thumb from {}", pv, e);
			// return new ReplyInfo<Object>(Constants.ERROR_UNKNOWN);
			return new ReplyInfo<Object>(Constants.ERROR_UNKNOWN, "Msg.flow.diagram");
		}
	}

	@RequestMapping("/edit")
	// @Authorized(code = "flow.edit")
	public void edit(HttpServletResponse rsp, String id, String code, String url, boolean flowOnly, FlowInfo fo, SvcInfo so) {
		flowInfoBiz.save(fo);
		if (!flowOnly) {
			svcBiz.save(so);
		}
		try {
			rsp.sendRedirect(url);
		} catch (IOException e) {
			log.error("Can not redirect to {}", url, e);
		}
	}

	@RequestMapping("/get.do")
	@Authorized(code = "flow.get")
	public String get(String id) {
		FlowInfo fo = flowInfoBiz.get(id);
		StringBuilder sb = new StringBuilder();
		sb.append("{ \"success\": true, \"data\": ");
		sb.append(JsonUtil.from(fo)).append(", \"byMe\": { \"0\": {}");
		List<SoaNexus> byLt = nexusBiz.listByMe(id);
		for (SoaNexus n : byLt) {
			sb.append(", \"").append(n.getObjId1()).append("\": ");
			sb.append(JsonUtil.from(n, "face,obj0,lib"));
		}
		sb.append(" }, \"onMe\": { \"0\": {}");
		List<SoaNexus> onLt = nexusBiz.listOnMe(id);
		for (SoaNexus n : onLt) {
			sb.append(", \"").append(n.getObjId1()).append("\": ");
			sb.append(JsonUtil.from(n, "face,obj1,lib"));
		}
		sb.append(" }, \"faces\": { \"0\": {}");
		PagedResult<ObjFaces> cfPr = objFacesBiz.list(id, "", "", "", "", 1, 9999);
		for (ObjFaces n : cfPr.getList()) {
			sb.append(", \"").append(n.getFaceId()).append("\": ");
			sb.append(JsonUtil.from(n.getFace()));
		}
		sb.append(" } }");
		return sb.toString();
	}

	/**
	 * 查询最近编辑的服务
	 */
	@RequestMapping("/find.do")
	@Authorized(code = "flow.find")
	public ReplyInfo<Object> find(int pageNo, int pageSize) {
		PagedResult<FlowInfo> pr = flowInfoBiz.find(pageNo, pageSize);
		return new ReplyInfo<Object>(true, JsonUtil.from(pr, "face"));
	}
}